<?php

namespace Aoe\Emulator\Ui\Widget;

use Aoe\Emulator\Ifc\Type;
use Aoe\Emulator\Schema\Element\Independent;
use Aoe\Emulator\Schema\Element\Relation;
use Aoe\Emulator\Ui\Context;
use Aoe\Emulator\Ui\Item;
use Throwable;

class Widget extends Item
{
    const string INPUT        = "input";
    const string AUTOCOMPLETE = "autocomplete";
    const string TEXT         = "textarea";
    const string SWITCH       = "switch";
    const string SLIDER       = "slider";
    const string DATE         = "date";
    const string TIME         = "time";
    const string SELECT       = "select";
    const string RADIO        = "radio";
    const string CHECKBOX     = "checkbox";
    const string TREE         = "tree";
    const string UPLOAD       = "file";
    const string IMG          = "img";
    const string WIDGET       = 'widget';

    protected static array $widgets = [
        Widget::CHECKBOX => Choice::class,
        Widget::RADIO    => Choice::class,
        Widget::SELECT   => Choice::class,
        Widget::TREE     => Choice::class,
        Widget::TIME     => Silver::class,
        Widget::DATE     => Gold::class,
        Widget::UPLOAD   => Attach::class,
        Widget::IMG      => Attach::class,
        Widget::AUTOCOMPLETE     => Choice::class,
    ];

    public static function renderWidget(Context $context, Independent $element, array $declarer): array
    {
        $widget = self::$widgets[$declarer[self::WIDGET] ?? self::getWidgetByElement($element)] ?? Widget::class;

        return new $widget($context, $element)->render($declarer);
    }

    public static function renderWidgets(Context $context, array $fields): array
    {
        return Item::renderItems($context, $fields, self::renderWidget(...));
    }

    /**
     * @param Independent $element
     *
     * @return string
     */
    public static function getWidgetByElement(Independent $element): string
    {
        if ($element->isRelation()) {
            try {
                /** @var Relation $element */
                $model = $element->getRelateModel();
                if ($model->isTree()) return Widget::TREE;
                return Widget::SELECT;
            } catch (Throwable) {
                return Widget::INPUT;
            }
        }

        if ($element->name === Type::STATUS) return Widget::SWITCH;

        return Widget::pascal2widget($element->getPascal());
    }
    
    public static function pascal2widget(string $pascal): string
    {
        return match ($pascal) {
            Type::BOOL => Widget::SWITCH,
            Type::TEXT => Widget::TEXT,
            Type::FILE => Widget::UPLOAD,
            Type::IMG  => Widget::IMG,
            Type::TIME => Widget::TIME,
            Type::DATE => Widget::DATE,
            Type::INTEGER => Widget::SLIDER,
            default => Widget::INPUT,
        };
    }

    public function render(?array $declarer = null): array
    {
        $declarer = parent::render($declarer);

        if (!isset($declarer[Type::DFT]) && $this->element->hasDefault())
            $declarer[Type::DFT] = $this->element->getDefault();

        $declarer[Type::RULES] = $this->_make_validator();

        return $declarer;
    }

    /**
     * 创建在线验证
     *
     * @return array
     */
    private function _make_validator(): array
    {
        $validator = array_map(
            fn ($valid) => is_string($valid) ? ['type' => strtolower($valid)] : $valid,
            $this->element->get(Type::RULES, []),
        );
        // 必填验证
        if ($this->element->must()) {
            $v           = [
                'required' => true,
                'message'  => '请输入' . $this->element->label,
            ];
            $validator[] = $v;
        }

        return $validator;
    }
}